﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Microsoft.WindowsCE.Forms;

namespace Scan
{
    public class Sound
    {
        [DllImport("CoreDll.DLL", EntryPoint = "PlaySoundW", SetLastError = true)]
        private extern static int PlaySoundBytesW(byte[] lpszName, IntPtr hModule, uint dwFlags);

        [DllImport("CoreDll.DLL", EntryPoint = "PlaySoundW", SetLastError = true)]
        private extern static int PlaySoundFileW(string szSound, IntPtr hMod, int flags);

        public enum PlaySoundFlags
        {
            SND_SYNC = 0x0000,
            SND_ASYNC = 0x0001,
            SND_NODEFAULT = 0x0002,
            SND_MEMORY = 0x0004,
            SND_LOOP = 0x0008,
            SND_NOSTOP = 0x0010,
            SND_NOWAIT = 0x00002000,
            SND_ALIAS = 0x00010000,
            SND_ALIAS_ID = 0x00110000,
            SND_FILENAME = 0x00020000,
            SND_RESOURCE = 0x00040004
        }

        public static int PlaySoundFile(string sFileName)
        {
            return PlaySoundFileW(sFileName, IntPtr.Zero, (int)(PlaySoundFlags.SND_ASYNC | PlaySoundFlags.SND_FILENAME));
        }

        public static void Beep()
        {
            Beep(BeepType.Default);
        }

        public static void Beep(BeepType type)
        {
            uint beeptype = 0;
            if (type == BeepType.Default)
            {
                beeptype = 0xffffffff;
            }
            else
            {
                beeptype = Convert.ToUInt32(type);
            }
            MessageBeep(beeptype);
        }

        [DllImport("CoreDll.DLL", EntryPoint = "MessageBeep", SetLastError = true)]
        private static extern void MessageBeep(uint type);

        public enum BeepType : int
        {
            /// <summary>
            /// Default beep sound.
            /// </summary>
            Default = 0,//0xFFFFFFFF,
            /// <summary>
            /// Sound played during an Asterisk MessageBox.
            /// </summary>
            Asterisk = 0x00000040,
            /// <summary>
            /// Sound played during an Exclamation MessageBox.
            /// </summary>
            Exclamation = 0x00000030,
            /// <summary>
            /// Sound played during a Question MessageBox.
            /// </summary>
            Question = 0x00000020,
            /// <summary>
            /// Sound played during a Hand MessageBox.
            /// </summary>
            Hand = 0x00000010,
        }
    }


    public class ScannerMsg 
    {

        public enum ResCode
        {
            RESULT_INITIALIZE = -1,
            RESULT_SUCCESS = 0,         // Operation was successful
            RESULT_ERR_BADFILENAME,
            RESULT_ERR_BADPORT,
            RESULT_ERR_BADREGION,
            RESULT_ERR_DRIVER,          // Error occurred communicating with engine driver
            RESULT_ERR_ENGINEBUSY,
            RESULT_ERR_FILE,
            RESULT_ERR_FILEINCOMPATIBLE,
            RESULT_ERR_FILEINVALID,
            RESULT_ERR_MEMORY,
            RESULT_ERR_NODECODE,
            RESULT_ERR_NODRIVER,
            RESULT_ERR_NOIMAGE,
            RESULT_ERR_NORESPONSE,
            RESULT_ERR_NOTCONNECTED,
            RESULT_ERR_PARAMETER,       // One of the function parameters was invalid
            RESULT_ERR_UNSUPPORTED,     // The operation was not supported by the engine
            RESULT_ERR_UPGRADE,
            RESULT_ERR_MENUDECODE,
            RESULT_ERR_REFLASH,
            RESULT_ERR_NOTRIGGER,       // "trigger" monitored during oemWaitForDecode has been "released"
            RESULT_ERR_BADSMARTIMAGE,
            RESULT_ERR_SMARTIMAGETOOLARGE,
            RESULT_ERR_BUFFER_TOO_SMALL,
            RESULT_ERR_TOO_MUCH_INTERPOLATION,
            RESULT_ERR_EXCEPTION
        };

        public enum EventFlags
        {
            PULSE = 1,
            RESET = 2,
            SET = 3
        }

        public enum SetupType
        {
            SETUP_TYPE_DEFAULT = 0,
            SETUP_TYPE_CURRENT,
        };

        [StructLayout(LayoutKind.Sequential)]
        public struct DecodeMessage
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
            public Char[] message;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public Char[] codeID;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public Char[] symLetter;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public Char[] symModifer;

            public ushort length;
        };

        [DllImport("oemdecodece.dll")]
        public static extern ResCode oemConnect();

        [DllImport("oemdecodece.dll")]
        public static extern ResCode oemEnableSymbologyAll();

        [DllImport("oemdecodece.dll")]
        public static extern ResCode oemSetDecodeMode(SetupType setupType, Char mode);

        public delegate Int32 CallBack();

        [DllImport("oemdecodece.dll")]
        public static extern ResCode oemWaitForDecode(
                          UInt32 time,
                          Char[] message,
                          Char[] codeID,
                          Char[] aimId,
                          Char[] symModifier,
                          ref UInt16 pnLength,
                          CallBack callBack);
    }

    public class ScannerMsgOne : MessageWindow
    {
        //接受的消息类型
        public enum ScannerMessage
        {
            SM_DATAREADY = 2,           //接收数据消息
        };

        //扫描提示方式
        public enum ScannerOK
        {
            SoundRemind = 1,			//扫描成功发音提示
            QuiverRemind = 2,           //扫描成功震动提示
            BothRemind = 3,             //扫描成功振铃提示
        };

        public enum BarcodeType
        {
            BCT_CODE_39,			// Code 39
            BCT_CODABAR,			// CodaBar
            BCT_CODE_128,			// Code 128
            BCT_DISCRETE_2OF5,      // Discrete 2 of 5
            BCT_INTERLEAVED_2OF5,	// Interleaves 2 of 5
            BCT_CODE_93,			// Code 93
            BCT_UPC_A,				// UPC A
            BCT_UPC_A_2SUPPS,		// UPC A with 2 Supps
            BCT_UPC_A_5SUPPS,		// UPC A with 5 Supps
            BCT_UPC_E0,				// UPC E
            BCT_UPC_E0_2SUPPS,		// UPC E with 2 Supps
            BCT_UPC_E0_5SUPPS,		// UPC E with 5 Supps 
            BCT_EAN_8,				// EAN 8
            BCT_EAN_13,				// EAN 13
            BCT_EAN_13_2SUPPS,		// EAN 13 with 2 Supps
            BCT_EAN_13_5SUPPS,		// EAN 13 with 5 Supps
            BCT_MSI_PLESSEY,		// MSI Plessey
            BCT_EAN_128,			// EAN 128
            BCT_UPC_E1,				// UPC E1
            BCT_UPC_E1_2SUPPS,		// UPC E1 with 2 Supps
            BCT_UPC_E1_5SUPPS,		// UPC E1 with 5 Supps
            BCT_TRIOPTIC_CODE_39,	// TRIOPTIC CODE 39
            BCT_BOOKLAND_EAN,		// Bookland EAN
            BCT_COUPON_CODE,		// Coupon Code
            BCT_RSS_14,             // RSS-14
            BCT_RSS_LIMITED,        // RSS-Limited
            BCT_RSS_EXPANDED,       // RSS-Expanded
            BCT_CODE_11,			// Code 11 
            BCT_CODE_32,			// Code 32
            BCT_CODE_39_FULLASCII,	// Code 39 full ascii
            BCT_ISBT_128,           // ISBT-128
            BCT_UNIDENTIFY,         // unidentifiable code
        };

        [StructLayout(LayoutKind.Sequential)]
        public struct BARCODE
        {
            public uint type;				// 条码的编码(原始)
            public uint len;				// 条码长度
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
            public String code;				// 条码
        };

        public struct SCANNER_PARAMS
        {
            // common
            public byte BeeperVolume;
            public byte BeeperTone;
            public byte BeeperFrequencyAdjustment;
            public byte LaserOnTime;
            public byte AimDuration;
            public byte ScanAngle;
            public byte PowerMode;
            public byte TriggerMode;
            public byte TimeoutBetweenSameSymbol;
            public byte BeepAfterGoodDecode;
            public byte TransmitNoReadMessage;
            public byte ParameterScanning;
            public byte LinearCodeTypeSecurityLevels;
            public byte BidirectionalRedundancy;

            // UPC/EAN
            public byte UPC_A;
            public byte UPC_E;
            public byte UPC_E1;
            public byte EAN_8;
            public byte EAN_13;
            public byte Bookland_EAN;
            public byte Decode_UPC_EAN_Supplementals;
            public byte Decode_UPC_EAN_SupplementalRedundancy;
            public byte Transmit_UPC_A_CheckDigit;
            public byte Transmit_UPC_E_CheckDigit;
            public byte Transmit_UPC_E1_CheckDigit;
            public byte UPC_A_Preamble;
            public byte UPC_E_Preamble;
            public byte UPC_E1_Preamble;
            public byte Convert_UPC_E_to_A;
            public byte Convert_UPC_E1_to_A;
            public byte EAN_8_ZeroExtend;
            public byte Convert_EAN_8_to_EAN_13_Type;
            public byte UPC_EAN_SecurityLevel;
            public byte UCC_CouponExtendCode;

            // Code 128
            public byte Code128;
            public byte UCC_EAN_128;
            public byte ISBT_128;

            // Code 39
            public byte Code39;
            public byte TriopticCode39;
            public byte Covert_Code39_to_Code32;
            public byte Code32Prefix;
            public byte SetLengthForCode39;
            public byte SetLengthForCode39_2;
            public byte Code39CheckDigitVerification;
            public byte TransmitCode39CheckDigit;
            public byte Code39FullAsciiConversion;

            // Code 93
            public byte Code93;
            public byte SetLengthForCode93;
            public byte SetLengthForCode93_2;

            // Code 11
            public byte Code11;
            public byte SetLengthForCode11;
            public byte SetLengthForCode11_2;
            public byte Code11CheckDigitVerification;
            public byte TransmitCode11CheckDigit;

            // Interleaved 2 of 5
            public byte Interleaved_2_5;
            public byte SetLengthFor_I2_5;
            public byte SetLengthFor_I2_5_2;
            public byte I2_5_CheckDigitVerification;
            public byte Transmit_I2_5_CheckDigit;
            public byte Convert_I2_5_to_EAN_13;

            // Descrete 2 of 5
            public byte Descrete_2_5;
            public byte SetLengthFor_D2_5;
            public byte SetLengthFor_D2_5_2;

            // Chinese 2 of 5
            public byte Chinese_2_5;

            // Codabar
            public byte Codabar;
            public byte SetLengthsForCodabar;
            public byte SetLengthsForCodabar_2;
            public byte CISI_Editing;
            public byte NOTIS_Editing;

            // MSI
            public byte MSI;
            public byte SetLengthsForMSI;
            public byte SetLengthsForMSI_2;
            public byte MSICheckDigits;
            public byte TransmitMSICheckDigit;
            public byte MSICheckDigitAlgorithm;

            // RSS
            public byte RSS_14;
            public byte RSS_Limited;
            public byte RSS_Expanded;
            public byte Covert_RSS_to_UPC_EAN;

            // Data options
            public byte TransmitCodeIDCharacter;
            public byte Prefix;
            public byte Suffix1;
            public byte Suffix2;
            public byte ScanDataTransmissionFormat;

            // Serial interface
            public byte BaudRate;
            public byte Parity;
            public byte SoftwareHandshaking;
            public byte DecodeDataPacketFormat;
            public byte HostSerialResponseTimeout;
            public byte StopBitSelect;
            public byte InterCharacterDelay;
            public byte HostCharacterTimeout;

            // Event reporting
            public byte DecodeEvent;
            public byte BootupEvent;
            public byte ParameterEvent;
        };

        // 初始化
        [DllImport("SSI2.dll")]
        public static extern bool SSI_Register(IntPtr hWnd, uint msgID);

        // 注销
        [DllImport("SSI2.dll")]
        public static extern void SSI_Unregister(IntPtr hWnd, uint msgID);

        // 获取条码队列中的第一个条码
        [DllImport("SSI2.dll")]
        public static extern bool SSI_GetData(ref BARCODE BarCode);

        // 获取条码队列中的第一个条码的名称
        [DllImport("SSI2.dll")]
        public static extern bool SSI_GetBarcodeName(StringBuilder buffer, int len);

        // 删除条码队列中的第一个条码
        [DllImport("SSI2.dll")]
        public static extern void SSI_ResetData();

        // 判断条码队列中是否有条码
        [DllImport("SSI2.dll")]
        public static extern bool SSI_IsDataReady();

        // 内置的提醒
        [DllImport("SSI2.dll")]
        public static extern void SSI_ReadOK(uint type);

        // 打开扫描功能，扫描头上电后默认就会打开扫描功能
        [DllImport("SSI2.dll")]
        public static extern bool SSI_EnableScan();

        // 关闭扫描功能
        [DllImport("SSI2.dll")]
        public static extern bool SSI_DisableScan();

        // 开始扫描
        [DllImport("SSI2.dll")]
        public static extern bool SSI_StartScan();

        // 停止扫描
        [DllImport("SSI2.dll")]
        public static extern bool SSI_StopScan();

        // 向扫描头发送命令
        [DllImport("SSI2.dll")]
        public static extern bool SSI_SendCommandString(byte[] command, int len);

        // 获取扫描头的配置参数
        [DllImport("SSI2.dll")]
        public static extern bool SSI_GetParams(ref SCANNER_PARAMS Params);

        // 设置扫描头的配置参数
        [DllImport("SSI2.dll")]
        public static extern bool SSI_SetParams(ref SCANNER_PARAMS Params);

        // 获得扫描头出厂时的参数
        [DllImport("SSI2.dll")]
        public static extern bool SSI_GetFactoryDefault(ref SCANNER_PARAMS Params);

        public delegate void ScannerReader(object sender, EventArgs e);
        public event ScannerReader OnScannerReader;

        public const int WM_READMSG = 0x0400;

        private Form msgform;

        public ScannerMsgOne(Form msgform)
        {
            this.msgform = msgform;
        }

        protected override void WndProc(ref Message msg)
        {
            switch (msg.Msg)
            {
                case WM_READMSG:
                    {
                        if (msg.WParam == (IntPtr)ScannerMessage.SM_DATAREADY)
                            OnScannerReader(this, new EventArgs());

                    }
                    break;
            }
            base.WndProc(ref msg);
        }
    }

}
